package com.huawei.spare.part.replace.utils;

import com.google.common.collect.Lists;
import com.huawei.spare.part.replace.Constants;
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.util.Zip4jConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;


public class ZipUtils {

    private static final Logger log = LoggerFactory.getLogger(ZipUtils.class);

    public static void zip(File src, File dst) throws ZipException {
        ZipFile zipFile = new ZipFile(dst);
        zipFile.setFileNameCharset(Constants.UTF8);
        ZipParameters parameters = new ZipParameters();
        parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
        parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
        ArrayList<File> files = new ArrayList<File>();
        getAllFile(src, files);
        zipFile.addFiles(files, parameters);
    }

    public static void unzip(File src, String dstFolder) throws ZipException {
        ZipFile zipFile = new ZipFile(src);
        zipFile.setFileNameCharset(Constants.UTF8);
        zipFile.extractAll(dstFolder);
    }

    public static void unzip(File src, String dstFolder, final List<File> list) throws ZipException {
        ZipFile zipFile = new ZipFile(src);
        zipFile.setFileNameCharset(Constants.UTF8);
        zipFile.extractAll(dstFolder);

        final File unzipSrc = new File(dstFolder);
        getAllFile(unzipSrc, list);
    }

    /**
     * extract a single file in zip file
     *
     * @param zipFilePath
     * @param extractFilePathInZip
     * @param destFolder
     * @param destFileName
     * @throws ZipException
     */
    public static void extract(File zipFilePath, String extractFilePathInZip,
                               String destFolder, String destFileName) throws ZipException {
        ZipFile zipFile = new ZipFile(zipFilePath);
        zipFile.setFileNameCharset(Constants.UTF8);
        final List<FileHeader> fileHeaders = zipFile.getFileHeaders();
        for (FileHeader fileHeader: fileHeaders) {
            if(fileHeader.getFileName().equals(extractFilePathInZip))  {
                zipFile.extractFile(fileHeader, destFolder, null, destFileName);
            }
        }
    }

    private static void getAllFile(final File src, final List<File> list) {
        if (src.isFile()) {
            list.add(src);
        } else if (src.isDirectory()) {
            File[] files = src.listFiles();
            if (files != null) {
                for (File file : files) {
                    getAllFile(file, list);
                }
            }
        }
    }

    public static List<String> getDirectEntryNames(File file) throws IOException {
        List<String> names = Lists.newArrayList();
        try (java.util.zip.ZipFile zipFile = new java.util.zip.ZipFile(file, Charset.forName(Constants.UTF8))) {
            Enumeration<? extends ZipEntry> entries = zipFile.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = entries.nextElement();
                names.add(entry.getName());
            }
        }
        return names;
    }

}
